package com.zyf.EasyNet.service.impl;

import com.zyf.EasyNet.dao.UserDAO;
import com.zyf.EasyNet.dataobject.UserDO;
import com.zyf.EasyNet.model.Result;
import com.zyf.EasyNet.model.User;
import com.zyf.EasyNet.param.state.Code;
import com.zyf.EasyNet.param.state.Message;
import com.zyf.EasyNet.service.UserService;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @first_author zyflzz
 * @gmt_created 2022/6/3
 * @gmt_modified 2022/6/3
 */
@Service
@Component
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDAO userDAO;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Result<User> register(String userName, String pwd) {

        Result<User> result = new Result<>();

        // 判断用户名、密码是否位空
        if (StringUtils.isEmpty(userName)) {
            result.setCode(Code.USERNAME_NULL);
            result.setMessage(Message.USERNAME_NULL);
            return result;
        }
        if (StringUtils.isEmpty(pwd)) {
            result.setCode(Code.PWD_NULL);
            result.setMessage(Message.PWD_NULL);
            return result;
        }

        /* 查找用户是否存在，如果存在那么不能重复注册 */
        // 先在 Redis 缓存中找，找不到再在数据库中找
        UserDO userDO = (UserDO) redisTemplate.opsForValue().get(userName);
        if (userDO == null) {
            userDO = userDAO.findByUserName(userName);
        }
        if (userDO != null) {
            result.setCode(Code.USER_ALREADY_EXIST);
            result.setMessage(Message.USER_ALREADY_EXIST);
            return result;
        }

        /* 使用 md5 算法对密码加密 */
        // 密码加自定义盐值，确保密码安全
        String saltPwd = pwd + "_zyf_pwd_2022";
        // 生成md5值，并转为大写字母
        String md5Pwd = DigestUtils.md5Hex(saltPwd).toUpperCase();

        // 设置用户 DO 数据
        UserDO regUserDO = new UserDO();
        regUserDO.setUserName(userName);
        // 初始昵称等于用户名
        regUserDO.setNickName(userName);
        regUserDO.setPwd(md5Pwd);

        // 添加用户到数据库
        userDAO.add(regUserDO);

        // 设置 Result 数据
        result.setCode(Code.SIGN_SUCCESS);
        result.setMessage(Message.SIGN_SUCCESS);
        result.setSuccess(true);
        result.setData(regUserDO.toModel());

        // 新用户注册成功后，还需要存入缓存
        redisTemplate.opsForValue().set(userName, regUserDO);

        return result;
    }

    @Override
    public Result<User> login(String userName, String pwd) {

        Result<User> result = new Result<>();

        // 判断用户名、密码是否为空
        if (StringUtils.isEmpty(userName)) {
            result.setCode(Code.USERNAME_NULL);
            result.setMessage(Message.USERNAME_NULL);
            return result;
        }
        if (StringUtils.isEmpty(pwd)) {
            result.setCode(Code.PWD_NULL);
            result.setMessage(Message.PWD_NULL);
            return result;
        }

        /* 查询用户，如果不存在说明用户未注册，不能登录，需要先注册 */
        UserDO userDO = (UserDO) redisTemplate.opsForValue().get(userName);

        if (userDO == null) {
            userDO = userDAO.findByUserName(userName);
            // 如果数据库中也找不到，那么需要先注册了，为了注册的时候减少消耗，先添加一个用户到缓存中，以备用，设置生命周期为5分钟
            if (userDO == null) {
                userDO = new UserDO();
                redisTemplate.opsForValue().set(userName, userDO, 5, TimeUnit.MINUTES);
                result.setCode(Code.USER_NOT_EXIST);
                result.setMessage(Message.USER_NOT_EXIST);
                return result;
            }
        }

        /* md5 算法不可逆，只能根据输入的密码按照规则重新加密，与数据库中的加密密码比较才能判断是否正确 */
        // 密码加自定义盐值，确保密码安全
        String saltPwd = pwd + "_zyf_pwd_2022";
        // 生成md5值，并转为大写字母
        String md5Pwd = DigestUtils.md5Hex(saltPwd).toUpperCase();
        // 密码不对不能登录
        if (!StringUtils.equals(md5Pwd, userDO.getPwd())) {
            result.setCode(Code.USERNAME_OR_PWD_WRONG);
            result.setMessage(Message.USERNAME_OR_PWD_WRONG);
            return result;
        }

        // 设置 Result 数据
        result.setCode(Code.LOGIN_SUCCESS);
        result.setMessage(Message.LOGIN_SUCCESS);
        result.setSuccess(true);
        result.setData(userDO.toModel());

        // 登录成功后更新缓存中的用户数据，因为可能缓存中原本没找到这个用户
        redisTemplate.opsForValue().set(userName, userDO);

        return result;
    }
}
